package sockerServer

import (
	"errors"
	"gitee.com/fierce_wolf/go-fox-edge-common/commEntity"
	"gitee.com/fierce_wolf/go-fox-edge-common/commRedisService"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/TcpServer"
	"gitee.com/fierce_wolf/go-fox-edge-common/edgeEntity"
	"go-fox-edge-channel-tcp-server-v2/channelEngine/channelHandler"
	"go-fox-edge-channel-tcp-server-v2/channelEngine/scriptEngine"
)

func StartTcpServer(serverPort int, param map[string]interface{}) error {
	manufacturer := Map.GetString(param, "manufacturer", "")
	deviceType := Map.GetString(param, "deviceType", "")

	// 创建一个ChannelHandler
	handler := &channelHandler.ChannelHandler{}
	handler.Notify = &channelHandler.OperateEntityNotify{}
	handler.Manufacturer = manufacturer
	handler.DeviceType = deviceType
	commRedisService.BindTypeNotify(edgeEntity.Type.OperateEntity.Type(), handler.Notify)

	// 创建一个ChannelNotify
	notify := &channelHandler.ChannelNotify{}
	notify.Manufacturer = manufacturer
	notify.DeviceType = deviceType
	notify.SessionHandler.Manufacturer = manufacturer
	notify.SessionHandler.DeviceType = deviceType

	// 初始化JS脚本引擎
	methods, library := getOperateEntityList(manufacturer, deviceType)
	for _, operateEntity := range methods {
		scriptEngine.ReloadScriptEngine(manufacturer, deviceType, operateEntity)

		if operateEntity.OperateMode == "splitHandler" {
			handler.SplitHandler = operateEntity.OperateName
		}
		if operateEntity.OperateMode == "keyHandler" {
			notify.KeyHandler = operateEntity.OperateName
		}
	}
	for _, operateEntity := range library {
		scriptEngine.ReloadScriptEngine(manufacturer, deviceType, operateEntity)
	}

	// 创建一个TCP Server
	server := TcpServer.TcpServer{}
	server.Port = serverPort
	server.Handler = handler
	server.Notify = notify

	go server.StartTcpServer()

	return nil
}

func getOperateEntityList(manufacturer, deviceType string) (methods, library []*edgeEntity.OperateEntity) {
	methods = make([]*edgeEntity.OperateEntity, 0)
	library = make([]*edgeEntity.OperateEntity, 0)

	commRedisService.FindEntityList(edgeEntity.Type.OperateEntity.Type(), func(entity commEntity.IEntity) bool {
		operateEntity := entity.(*edgeEntity.OperateEntity)

		if operateEntity.Manufacturer != manufacturer {
			return false
		}
		if operateEntity.DeviceType != deviceType {
			return false
		}
		if operateEntity.EngineType != "JavaScript" {
			return false
		}
		if operateEntity.ServiceType != "channel" {
			return false
		}

		if operateEntity.OperateMode == "include" {
			library = append(library, operateEntity)
		} else {
			methods = append(methods, operateEntity)
		}

		return true
	})

	return methods, library
}

func getOperateEntity(manufacturer, deviceType, operateName string) (*edgeEntity.OperateEntity, error) {
	operateEntity := commRedisService.GetOperateEntity(manufacturer, deviceType, operateName)
	if operateEntity == nil {
		return nil, errors.New("找不到对应的解码器：" + " Manufacturer->" + manufacturer + " DeviceType->" + deviceType + " OperateName->" + operateName)
	}

	// 引擎类型检查
	if operateEntity.EngineType != "JavaScript" {
		return nil, errors.New("只支持JavaScript类型的解码器引擎")
	}
	if operateEntity.ServiceType != "channel" {
		return nil, errors.New("只支持channel类型的解码器引擎")
	}

	return operateEntity, nil
}
